#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#define err_exit(MSG) (perror(MSG), exit(-1))
int main()
{
    /*父进程派生两个子进程*/
    pid_t child1 = fork();
    /**
     * @brief child1进程
     * 
     */
    if (child1 < 0)
    {
        err_exit("fork child1 failed!");
    }
    else if (child1 == 0)
    {
        /*child1的代码*/
        printf("  [child1] : child1 = %d , pid = %d , ppid = %d\n", child1, getpid(), getppid());
        sleep(1); // 休眠1s
        printf("  [child1] : child1 exit\n");
        exit(0);
    }
    else
    {
        /*父进程的代码*/
        printf("[parent] : child1 = %d , pid = %d , ppid = %d\n", child1, getpid(), getppid());
        printf("[parent] : wait child1 exit\n");
        waitpid(child1, NULL, 0); //parent等待子进程1结束
        printf("[parent] : child1 has exited\n");
    }
    /**
     * @brief child2进程
     * 
     */
    pid_t child2 = fork();
    if (child2 < 0)
    {
        err_exit("fork child2 failed!");
    }
    else if (child2 == 0)
    {
        /*child1的代码*/
        printf("  [child2] : child2 = %d , pid = %d , ppid = %d\n", child2, getpid(), getppid());

        /*子进程2派生子进程2_1和2_2*/
        pid_t child2_1 = fork();
        /**
         * @brief child2_1进程
         * 
         */
        if (child2_1 < 0)
        {
            err_exit("fork child2_1 failed!");
        }
        else if (child2_1 == 0)
        {
            /*child2_1的代码*/
            printf("    [child2_1] : child2_1 = %d , pid = %d , ppid = %d\n", child2_1, getpid(), getppid());
            sleep(2); //休眠2s
            printf("    [child2_1] exit\n");
            exit(0);
        }
        else
        {
            /*child2进程的代码*/
            printf("  [child2] : child2_1 = %d , pid = %d , ppid = %d\n", child2_1, getpid(), getppid());
            printf("  [child2] : wait child2_1 exit\n");
            waitpid(child2_1, NULL, 0); //child2等待child2_1结束
            printf("  [child2] : child2_1 has exited\n");
        }
        /**
         * @brief child2_2进程
         * 
         */
        pid_t child2_2 = fork();
        if (child2_2 < 0)
        {
            err_exit("fork child2_2 failed!");
        }
        else if (child2_2 == 0)
        {
            /*child2_2的代码*/
            printf("    [child2_2] : child2_2 = %d , pid = %d , ppid = %d\n", child2_2, getpid(), getppid());
            sleep(4); //休眠4秒
            printf("    [child2_2] exit\n");
            exit(0);
        }
        else
        {
            /*child2进程的代码*/
            printf("  [child2] : child2_2 = %d , pid = %d , ppid = %d\n", child2_2, getpid(), getppid());
            printf("  [child2] : wait child2_2 exit\n");
            waitpid(child2_2, NULL, 0); //child2进程等待进程child2_2结束
            printf("  [child2] : child2_2 has exited\n");
        }

        sleep(3); //休眠3s
        printf("  [child2] : child2 exit\n");
        exit(0);
    }
    else
    {
        /*父进程的代码*/
        printf("[parent] : child2 = %d , pid = %d , ppid = %d\n", child2, getpid(), getppid());
        printf("[parent] : wait child2 exit\n");
        waitpid(child2, NULL, 0); //等待子进程2结束
        printf("[parent] : child2 has exited\n");
        printf("[parent] : parent exit\n");
        exit(0);
    }
}